﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using System.Xml.Linq;
using Microsoft.Xrm.Sdk.Query;
using System.IO;
using System.Diagnostics;

namespace Ragim.Selfpub.CrmSolution.Plugins.Tools
{
    public static class Integration
    {
        public static bool CreateLead(string firstName, string lastName, string phone, string email, string url, string campaign, out string error)
        {
            string step = "заполнение сущности";
            Entity lead = new Entity("lead");
            lead["firstname"] = firstName;
            lead["lastname"] = lastName;
            lead["mobilephone"] = phone;
            lead["emailaddress1"] = email;
            lead["websiteurl"] = url;
            lead["subject"] = campaign;

            step = "создание сервиса";
            using (var service = Util.GetService_online())
            {
                try
                {
                    step = "получение настроек";
                    CrmSettings set = new CrmSettings(service);
                    lead["ownerid"] = set.CallcenterTeam;

                    step = "создание сущности";
                    service.Create(lead);
                    error = "";
                    return true;
                }
                catch (Exception ex)
                {
                    string str = string.Format("Произошла ошибка при создании Интереса [этап '{1}']: {0}", ex.ToString(), step);
                    var innerEx = ex.InnerException;
                    while (innerEx != null)
                        str += Environment.NewLine + Environment.NewLine + string.Format("Внутрення ошибка: {0}", innerEx.ToString());

                    error = str;
                    return false;
                }
                finally
                {
                    service.Dispose();
                }
            }
        }

        private static XDocument CreateXMLForQuote(IOrganizationService service, Guid quoteId)
        {
            var quote = service.Retrieve_Custom("quote", quoteId, new ColumnSet("customerid", "opportunityid", "quotenumber",
                "new_book_name", "new_count_of_pages", "new_circulation", "new_format_of_page",
                "new_format_of_page_other", "new_colourfull", "new_count_of_pictures", "new_colorfull_of_pictures", "new_paper_type",
                "new_paper_type_other", "new_book_cover", "new_colourfull_of_cover", "new_lamination_of_cover"));

            #region customerid
            var customerRef = quote.GetEntityReferenceAttributeValue("customerid");
            string contact_name = "";
            string contact_fio = "";
            string contact_phone = "";
            string contact_email = "";
            string contact_gender = "";
            if (customerRef != null && customerRef.LogicalName == "contact")
            {
                var customer = service.Retrieve_Custom(customerRef, new ColumnSet(
                    "lastname", "firstname", "mobilephone", "emailaddress1", "gendercode"));
                contact_name = customer.GetStringAttributeValue("firstname");
                contact_fio = string.Format("{0} {1}", customer.GetStringAttributeValue("lastname"), customer.GetStringAttributeValue("firstname"));
                contact_phone = customer.GetStringAttributeValue("mobilephone");
                contact_email = customer.GetStringAttributeValue("emailaddress1");
                contact_gender = (customer.GetOptionSetAttributeValue("gendercode") ?? 1).ToString();
            }
            #endregion

            #region ooportunity
            var opportunityRef = quote.GetEntityReferenceAttributeValue("opportunityid");
            string opportunity_createdon = "";
            string opportunity_owner_fio = "";
            string opportunity_owner_phone = "";
            string opportunity_owner_email = "";
            if (opportunityRef != null)
            {
                var opportunity = service.Retrieve_Custom(opportunityRef, new ColumnSet("createdon", "ownerid"));
                opportunity_createdon = opportunity.GetDateTimeAttributeValue("createdon").Value.ToLocalTime().ToString("dd.MM.yyyy");
                var _ownerRef = opportunity.GetEntityReferenceAttributeValue("ownerid");

                var _owner = service.Retrieve_Custom(_ownerRef, new ColumnSet("lastname", "firstname", "mobilephone", "internalemailaddress"));
                opportunity_owner_fio = string.Format("{0} {1}", _owner.GetStringAttributeValue("lastname"), _owner.GetStringAttributeValue("firstname"));
                opportunity_owner_phone = _owner.GetStringAttributeValue("mobilephone");
                opportunity_owner_email = _owner.GetStringAttributeValue("internalemailaddress");
            }
            #endregion

            #region quote
            var quotenumber = quote.GetStringAttributeValue("quotenumber");
            var new_book_name = quote.GetStringAttributeValue("new_book_name");
            var new_count_of_pages = quote.GetIntAttributeValue("new_count_of_pages");
            var new_circulation = quote.GetIntAttributeValue("new_circulation");

            var new_format_of_page = quote.GetOptionSetAttributeValue("new_format_of_page");
            var new_format_of_page_other = quote.GetStringAttributeValue("new_format_of_page_other");
            string new_format_of_page_text = "";
            if (new_format_of_page.HasValue)
                if (new_format_of_page == 100000003)
                    new_format_of_page_text = new_format_of_page_other;
                else
                    new_format_of_page_text = service.GetPickList("quote", "new_format_of_page")[new_format_of_page.Value];

            var new_colourfull = quote.GetOptionSetAttributeValue("new_colourfull");
            string new_colourfull_text = "";
            if (new_colourfull.HasValue)
                new_colourfull_text = service.GetPickList("quote", "new_colourfull")[new_colourfull.Value];

            var new_count_of_pictures = quote.GetIntAttributeValue("new_count_of_pictures");

            var new_colorfull_of_pictures = quote.GetOptionSetAttributeValue("new_colorfull_of_pictures");
            string new_colorfull_of_pictures_text = "";
            if (new_colorfull_of_pictures.HasValue)
                new_colorfull_of_pictures_text = service.GetPickList("quote", "new_colorfull_of_pictures")[new_colorfull_of_pictures.Value];

            var new_paper_type = quote.GetOptionSetAttributeValue("new_paper_type");
            var new_paper_type_other = quote.GetStringAttributeValue("new_paper_type_other");
            string new_paper_type_text = "";
            if (new_paper_type.HasValue)
                if (new_paper_type == 100000002)
                    new_paper_type_text = new_paper_type_other;
                else
                    new_paper_type_text = service.GetPickList("quote", "new_paper_type")[new_paper_type.Value];

            var new_book_cover = quote.GetOptionSetAttributeValue("new_book_cover");
            string new_book_cover_text = "";
            if (new_book_cover.HasValue)
                new_book_cover_text = service.GetPickList("quote", "new_book_cover")[new_book_cover.Value];

            var new_colourfull_of_cover = quote.GetOptionSetAttributeValue("new_colourfull_of_cover");
            string new_colourfull_of_cover_text = "";
            if (new_colourfull_of_cover.HasValue)
                new_colourfull_of_cover_text = service.GetPickList("quote", "new_colourfull_of_cover")[new_colourfull_of_cover.Value];

            var new_lamination_of_cover = quote.GetOptionSetAttributeValue("new_lamination_of_cover");
            string new_lamination_of_cover_text = "";
            if (new_lamination_of_cover.HasValue)
                new_lamination_of_cover_text = service.GetPickList("quote", "new_lamination_of_cover")[new_lamination_of_cover.Value];
            #endregion

            var doc = new XDocument(new XDeclaration("1.0", "windows-1251", "no"));

            XElement ROOT = new XElement("ROOT");

            ROOT.Add(new XAttribute("Version", "2.0"));
            doc.Add(ROOT);

            ROOT.Add(CreateMacroNode("Контакт_ФИО", contact_fio));
            ROOT.Add(CreateMacroNode("Контакт_Мобильный_Телефон", contact_phone));
            ROOT.Add(CreateMacroNode("Контакт_Электронная_Почта", contact_email));
            ROOT.Add(CreateMacroNode("Возможная_Сделка_Дата_Создания", opportunity_createdon));
            ROOT.Add(CreateMacroNode("КодПредложения", quotenumber));
            ROOT.Add(CreateMacroNode("Текущая_Дата", DateTime.Now.ToString("dd.MM.yyyy")));
            ROOT.Add(CreateMacroNode("Контакт_Пол", contact_gender));//contact_name
            ROOT.Add(CreateMacroNode("Контакт_Имя", contact_name));
            ROOT.Add(CreateMacroNode("Возможная_Ответственный_ФИО", opportunity_owner_fio));
            ROOT.Add(CreateMacroNode("Возможная_Ответственный_Мобильный_Телефон", opportunity_owner_phone));
            ROOT.Add(CreateMacroNode("Возможная_Ответственный_Основной_адрес_электронной_почты", opportunity_owner_email));

            #region quoteDetails
            var query = new QueryExpression()
            {
                EntityName = "quotedetail",
                NoLock = true,
                ColumnSet = new ColumnSet("productid", "uomid", "priceperunit", "quantity", "manualdiscountamount", "extendedamount", "new_annotation"),
                Criteria = new FilterExpression(LogicalOperator.And)
                {
                    Conditions =
                    {
                        new ConditionExpression("quoteid", ConditionOperator.Equal, quoteId)
                    }
                },
                LinkEntities =
                {
                    new LinkEntity("quotedetail", "product", "productid", "productid", JoinOperator.Inner)
                    {
                        LinkEntities = 
                        {
                            new LinkEntity("product", "subject", "subjectid", "subjectid", JoinOperator.Inner)
                            {
                                EntityAlias = "subject",
                                Columns = new ColumnSet("description")
                            }
                        }
                    }
                }
            };

            var quoteDetails = service.RetrieveMultiple_Custom(query);

            var quoteDetails_1 = quoteDetails.Where(x => x.GetStringAttributeValue("subject.description") == "1").ToList();
            var total1 = Math.Round(quoteDetails_1.Sum(x => x.GetMoneyAttributeValue("extendedamount") ?? 0), 2);

            ROOT.Add(CreateMacroNode("Есть_Продукты_с_темой_РИУ", (quoteDetails_1.Count > 0) ? "1" : "0"));
            if (quoteDetails_1.Count > 0)
            {
                ROOT.Add(CreateMacroNode("Название", new_book_name));
                ROOT.Add(CreateMacroNode("Количество_страниц", new_count_of_pages.HasValue ? new_count_of_pages.Value.ToString() : ""));
                ROOT.Add(CreateMacroNode("Тираж", new_circulation.HasValue ? new_circulation.Value.ToString() : ""));
                ROOT.Add(CreateMacroNode("Формат", new_format_of_page_text));
                ROOT.Add(CreateMacroNode("Блок", new_colourfull_text));
                ROOT.Add(CreateMacroNode("Количествово_иллюстраций_в_блоке", new_count_of_pictures.HasValue ? new_count_of_pictures.Value.ToString() : ""));
                ROOT.Add(CreateMacroNode("Цветность_иллюстраций_в_блоке", new_colorfull_of_pictures_text));
                ROOT.Add(CreateMacroNode("Бумага", new_paper_type_text));
                ROOT.Add(CreateMacroNode("Переплёт", new_book_cover_text));
                ROOT.Add(CreateMacroNode("Цветность_обложки", new_colourfull_of_cover_text));
                ROOT.Add(CreateMacroNode("Ламинация_обложки", new_lamination_of_cover_text));

                ROOT.Add(CreateMacroNode("Продукты_с_темой_РИУ_сумма_целая_часть",
                    Convert.ToInt32(Math.Truncate(total1)).ToString()));
                ROOT.Add(CreateMacroNode("Продукты_с_темой_РИУ_сумма_дробная_часть",
                    Convert.ToInt32((total1 - Math.Truncate(total1)) * 100).ToString()));

                ROOT.Add(GetProductDetatilsTable(quoteDetails_1, "1"));
            }

            var quoteDetails_2 = quoteDetails.Where(x => x.GetStringAttributeValue("subject.description") == "2").ToList();
            var total2 = Math.Round(quoteDetails_2.Sum(x => x.GetMoneyAttributeValue("extendedamount") ?? 0), 2);

            ROOT.Add(CreateMacroNode("Есть_Продукты_с_темой_УпП", (quoteDetails_2.Count > 0) ? "1" : "0"));
            if (quoteDetails_2.Count > 0)
            {
                ROOT.Add(CreateMacroNode("Продукты_с_темой_УпП_сумма_целая_часть",
                    Convert.ToInt32(Math.Truncate(total2)).ToString()));
                ROOT.Add(CreateMacroNode("Продукты_с_темой_УпП_сумма_дробная_часть",
                    Convert.ToInt32((total2 - Math.Truncate(total2)) * 100).ToString()));

                ROOT.Add(GetProductDetatilsTable(quoteDetails_2, "2"));
            }
            #endregion

            return doc;
        }

        private static XElement GetProductDetatilsTable(List<Entity> quoteDeteils, string index)
        {
            XElement _table1 = new XElement("Table");
            foreach (var item in quoteDeteils)
            {
                XElement _String = new XElement("String");

                var productid = item.GetEntityReferenceAttributeValue("productid");
                var uomid = item.GetEntityReferenceAttributeValue("uomid");
                var priceperunit = item.GetMoneyAttributeValue("priceperunit");
                var quantity = item.GetDecimalAttributeValue("quantity");
                var manualdiscountamount = item.GetMoneyAttributeValue("manualdiscountamount");
                var extendedamount = item.GetMoneyAttributeValue("extendedamount");
                var new_annotation = item.GetStringAttributeValue("new_annotation");

                _String.Add(CreateMacroNode("Продукт_Название" + index, (productid ?? new EntityReference()).Name));
                _String.Add(CreateMacroNode("Продукт_Ед_изм" + index, (uomid ?? new EntityReference()).Name));
                _String.Add(CreateMacroNode("Продукт_Цена" + index, (priceperunit.HasValue ? priceperunit.Value.ToString("F") : "")));
                string _quantity_str = "";
                if (quantity.HasValue)
                {
                    _quantity_str = quantity.Value.ToString();
                    while ((_quantity_str.Last() == '0' && (_quantity_str.Contains(',') || _quantity_str.Contains('.'))) ||
                        _quantity_str.Last() == ',' || _quantity_str.Last() == '.')
                    {
                        _quantity_str = _quantity_str.Substring(0, _quantity_str.Length - 1);
                    }
                }
                _String.Add(CreateMacroNode("Продукт_Количество" + index, _quantity_str));
                _String.Add(CreateMacroNode("Продукт_Скидка" + index, (manualdiscountamount.HasValue ? manualdiscountamount.Value.ToString("F") : "")));
                _String.Add(CreateMacroNode("Продукт_ПолнаяСумма" + index, (extendedamount.HasValue ? extendedamount.Value.ToString("F") : "")));
                _String.Add(CreateMacroNode("Продукт_Примечание" + index, new_annotation));

                _table1.Add(_String);
            }
            return _table1;
        }

        private static XElement CreateMacroNode(string name, string value)
        {
            XElement _node = new XElement("Macro");
            _node.Add(new XAttribute("Name", name));
            _node.Add(new XAttribute("Value", value));

            return _node;
        }

        private static byte[] GenerateQuoteDoc(XDocument doc, string connStr)
        {
            string step = "";
            try
            {
                var InputXMLFileName = @"C:\temp\InputData" + Guid.NewGuid().ToString() + ".xml";
                var OutputFileName = @"C:\temp\OutputDocumentName" + Guid.NewGuid().ToString() + ".xml";

                step = "Сохранение файла с XML";
                doc.Save(InputXMLFileName);

                step = "SBLogon.LoginPoint()";
                var DIRECTUMLoginPoint = new SBLogon.LoginPoint();
                step = "DIRECTUMLoginPoint.GetApplication()";
                var _DIRECTUMConnection = DIRECTUMLoginPoint.GetApplication(connStr);
                //var _DIRECTUMConnection = DIRECTUMLoginPoint.GetApplication("SystemCode=EmptyDIR50;UserName=Administrator;Password=1Qwerty;IsOSAuth=False;IsVirtualPassword=False;");

                step = "_DIRECTUMConnection.ScriptFactory";
                SBRte.IScript Script = _DIRECTUMConnection.ScriptFactory.GetObjectByName("CreateDocumentFromXML");
                Script.Params.Add("TemplateID", "147648");
                Script.Params.Add("InputXMLFilePath", InputXMLFileName);
                Script.Params.Add("OutputFilePath", OutputFileName);
                step = "Script.Execute";
                Script.Execute();

                step = "чтенине doc файла";
                var result = File.ReadAllBytes(OutputFileName);

                step = "удаление файлов";
                File.Delete(InputXMLFileName);
                File.Delete(OutputFileName);

                return result;
            }
            catch (Exception ex)
            {
                string str = string.Format("Во время генерации КП произошла ошибка [этап '{1}']: {0}", ex.ToString(), step);
                var innerEx = ex.InnerException;
                while (innerEx != null)
                    str += Environment.NewLine + Environment.NewLine + string.Format("Внутрення ошибка: {0}", innerEx.ToString());

                throw new Exception(str);
            }
        }

        public static bool ExportQuote(Guid quoteId, string connStr, out string error)
        {
            string step = "";
            step = "создание сервиса";
            using (var service = Util.GetService_online())
            {
                try
                {
                    step = "генерация XML";
                    var doc = CreateXMLForQuote(service, quoteId);

                    step = "генерация файла";
                    var data = GenerateQuoteDoc(doc, connStr);

                    string encodedData = System.Convert.ToBase64String(data);

                    step = "прикрепить файл";
                    Entity note = new Entity("annotation");
                    note["objectid"] = new EntityReference("quote", quoteId);
                    note["subject"] = "Коммерческое предложение";
                    note["documentbody"] = encodedData;
                    note["mimetype"] = @"application\ms-word";
                    note["notetext"] = "Коммерческое предложение от " + DateTime.Now.ToString("dd.MM.yyyy HH:mm");
                    note["filename"] = "quote_" + DateTime.Now.ToString("dd-MM-yyyy") + ".doc";

                    service.Create(note);


                    error = "";
                    return true;
                }
                catch (Exception ex)
                {
                    string str = string.Format("Во время создания КП произошла ошибка [этап '{1}']: {0}", ex.ToString(), step);
                    var innerEx = ex.InnerException;
                    while (innerEx != null)
                        str += Environment.NewLine + Environment.NewLine + string.Format("Внутрення ошибка: {0}", innerEx.ToString());

                    error = str;
                    return false;
                }
                finally
                {
                    service.Dispose();
                }
            }
        }
    }
}
